<template>
  <div class="login-page">
    <h2>登录</h2>
    <div>
      <label>手机号</label>
      <input v-model="userPhone" placeholder="请输入手机号" />
    </div>
    <div>
      <label>密码</label>
      <input v-model="password" type="password" placeholder="请输入密码" />
    </div>
    <div class="actions">
      <button @click="submit" :disabled="loading">登录</button>
    </div>
    <div v-if="error" class="error">{{ error }}</div>
  </div>
</template>

<script>
// import axios from 'axios'
import http from '@/services/http'

export default {
  name: 'Login',
  data() {
    return {
      userPhone: '',
      password: '',
      loading: false,
      error: ''
    }
  },
  methods: {
    // 把 PEM 公钥字符串转换为 ArrayBuffer (spki)
    pemToArrayBuffer(pem) {
      const b64 = pem
        .replace(/-----BEGIN PUBLIC KEY-----/g, '')
        .replace(/-----END PUBLIC KEY-----/g, '')
        .replace(/\s+/g, '')
      const binary = atob(b64)
      const len = binary.length
      const bytes = new Uint8Array(len)
      for (let i = 0; i < len; i++) {
        bytes[i] = binary.charCodeAt(i)
      }
      return bytes.buffer
    },

    // ArrayBuffer -> base64
    arrayBufferToBase64(buffer) {
      const bytes = new Uint8Array(buffer)
      let binary = ''
      for (let i = 0; i < bytes.byteLength; i++) {
        binary += String.fromCharCode(bytes[i])
      }
      return btoa(binary)
    },

    // 使用浏览器 SubtleCrypto 导入公钥并用 RSA-OAEP (SHA-256) 加密
    async encryptPasswordWithPem(password, publicKeyPem) {
      try {
        const spki = this.pemToArrayBuffer(publicKeyPem)
        const key = await window.crypto.subtle.importKey(
          'spki',
          spki,
          {
            name: 'RSA-OAEP',
            hash: { name: 'SHA-256' }
          },
          false,
          ['encrypt']
        )
        const encoded = new TextEncoder().encode(password)
        const encrypted = await window.crypto.subtle.encrypt(
          { name: 'RSA-OAEP' },
          key,
          encoded
        )
        return this.arrayBufferToBase64(encrypted)
      } catch (err) {
        throw new Error('密码加密失败：' + (err.message || err))
      }
    },

    async submit() {
      this.error = ''
      this.loading = true
      try {
        // 后端提供的公钥（使用时按后端给定字符串替换）
        const publicKeyPem = `-----BEGIN PUBLIC KEY-----MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA6cjReuGBme+AbQpdgQiyNzfbZoFTPSDg
MXzbPr2XSljF85D3iK5EEB8FyIRMUgqmewr4wXzDTvCQg+s3L46ffYw+0dWwJsSi+2lz34UKwxxp
Tq0nbyC158roBrhvKpD4Dik5bfhmcbBwy/4aXjWIl8WwTWNxyFd9DO2rSAxHE7Fl3LDiCgS/jmwh
jT80jvSmLv5ObfaEhQMeSFGbDu9rSVgDN/PJzqzx97RxUddddSNK5VuUv+ouYWi5qmMPE6iKyA0F
Nnn0AL2TSNcXu0qZvMkOLAGAngM1H90DN6bk8deG5wLfSKmnttYviGsLUBdrfZssoj5imCMpYTeg
R+3uFE7UrwiOX2EbLyW+nTfYKuIDbpgT3i75lAJYGA2IPi5vHUGR3CxwWtmXtr0Xr7wTDNPy9Dq3
Rmr+vdMT2GLGXMpYUtrstyi2H6tdjk+jr2fosmboz+5A6FmINLLdFMQyeO1iG8rNxzxDZgidL4Iq
aJ3MVWuTBx8YfjWm7Ei1aAjlAgMBAAE=-----END PUBLIC KEY-----`

        const encryptedPassword = await this.encryptPasswordWithPem(this.password, publicKeyPem)

        const payload = {
          userPhone: this.userPhone,
          password: encryptedPassword
        }

        const res = await http.post('/api/login/logins/web', payload)

        // 后端直接返回 token 字符串的情况，或返回对象时尝试常见字段
        let token = res.data
        if (typeof token === 'object') {
          token =
            token.token ||
            token.accessToken ||
            (token.data && (token.data.token || token.data.accessToken)) ||
            null
        }

        if (!token) {
          this.error = '登录失败：未收到 token'
          this.loading = false
          return
        }

        localStorage.setItem('jwt_token', token)
        http.defaults.headers.common['Authorization']= 'Bearer ' + token
        this.$router.push({ path: '/showTime' })
      } catch (e) {
        this.error = e.response?.data?.message || e.message || '请求失败'
      } finally {
        this.loading = false
      }
    }
  }
}
</script>

<style scoped>
.login-page { max-width: 420px; margin: 40px auto; }
input { display: block; width: 100%; margin: 6px 0 12px; padding: 8px; }
button { padding: 8px 16px; }
.error { color: red; margin-top: 8px; }
</style>